package erfgame.core.graphics.renderer.chain;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.image.BufferedImage;


import erfgame.core.entity.Entity;
import erfgame.core.graphics.renderer.EntityRenderer;
import erfgame.core.graphics.renderer.PrototypeEntityRenderer;
import erfgame.core.graphics.renderer.RendererUpdateType;
import erfgame.core.world.World;

public class ChainedOutlineRenderer 
	extends AbstractChainedRenderer 
	implements PrototypeEntityRenderer{
	
	private BufferedImage selectionBuffer;
	private BufferedImage highlightBuffer;
	private Color selectionColor;
	private int selectionColorRGB;
	
	public ChainedOutlineRenderer( Color selectionColor ) {
		this.selectionColor = selectionColor;
		this.selectionColorRGB = selectionColor.getRGB() & 0xFFFFFF;
	}

	@Override
	public void setChild(EntityRenderer child, boolean started) {
		if( child != null && started ) {
			super.setChild(child, started);
			createBuffers();
			rendererUpdated(RendererUpdateType.content, null);
		} else {
			super.setChild(child, started);
			clearBuffers();
		}
	}
	
	@Override
	public void start() {
		createBuffers();
		super.start();
	}
	
	protected void createBuffers() {
		Dimension dimension = child.getDimension();
		// TODO create only if started
		this.selectionBuffer = new BufferedImage( 
				dimension.width, 
				dimension.height,
				BufferedImage.TYPE_INT_ARGB
		);
		this.highlightBuffer = new BufferedImage( 
				dimension.width, 
				dimension.height,
				BufferedImage.TYPE_INT_ARGB
		);
		redraw();
	}

	@Override
	public void stop() {
		clearBuffers();
		super.stop();
	}
	
	protected void clearBuffers() {
		this.selectionBuffer = null;
		this.highlightBuffer = null;
	}

	public void render(Graphics g, int x, int y) {
		g.drawImage( highlightBuffer, x, y, null );
	}

	public void rendererUpdated( RendererUpdateType type, Object state ) {
		redraw();
		super.rendererUpdated(type, state);
	}
	
	private void redraw() {
		EntityRenderer child = this.getChild();
		// clear selection buffer
		for(int ix=selectionBuffer.getWidth(); ix>0; ) {
			ix--;
			for( int iy=selectionBuffer.getHeight(); iy>0; ) {
				iy--;
				selectionBuffer.setRGB(ix, iy, 0x00FFFFFF);
				highlightBuffer.setRGB(ix, iy, 0x00FFFFFF);
			}
		}
		Graphics buffer = this.selectionBuffer.getGraphics();
		// TODO use a real red outline
	//		Graphics ng = g.create();
	//		ng.setXORMode(Color.red);
		child.render(buffer, 0, 0);
		for(int ix=selectionBuffer.getWidth(); ix>0; ) {
			ix--;
			for( int iy=selectionBuffer.getHeight(); iy>0; ) {
				iy--;
	//				selectionBuffer.setRGB(ix, iy, selectionModel.getRGB(selectionBuffer.getRGB(ix, iy)));
				int px = (selectionBuffer.getRGB(ix, iy) & 0xFF000000) | selectionColorRGB;
				selectionBuffer.setRGB(ix, iy, px);
			}
		}
		Graphics g = highlightBuffer.getGraphics();
	//		this.proxied.render(ng, x, y+2);
	//		this.proxied.render(ng, x+2, y);
	//		this.proxied.render(ng, x+2, y+2);
		buffer.dispose();
		selectionBuffer.flush();
		g.drawImage( selectionBuffer, -1, -1, null );
		g.drawImage( selectionBuffer, +1, -1, null );
		g.drawImage( selectionBuffer, -1, +1, null );
		g.drawImage( selectionBuffer, +1, +1, null );
		child.render(g, 0, 0);
		g.dispose();
	}

	public ChainedOutlineRenderer spawn( World world, Entity entity ) {
		ChainedOutlineRenderer result = new ChainedOutlineRenderer(
				this.selectionColor
		);
		result.setType( this.getType() );
		result.setPriority( this.getPriority() );
		return result;
	}
}